/****************************************************************
 * Fulguro
 * Copyright (C) 2004 Christophe Clienti
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 ***************************************************************/

#include <stdio.h> 
#include <stdlib.h>
#include <flgrCoreMalloc.h>
#include <flgrCoreDispatch.h>
#include "flgrDataToolsList.h" 
 
/*!
 * \defgroup group_fulguro_datatools Data tools
 * \brief Basic tools for manipulating data
 * \defgroup group_fulguro_datatools_list Lists
 * \brief Basic tools for manipulating Lists
 * \ingroup group_fulguro_datatools
 * @{
 */


//////////////////////////////////////////////////////////////////
/*! Test if a list is empty
 *  @param list : FLGR_List
 *  @returns FLGR_TRUE if empty else FLGR_FALSE
 */
//////////////////////////////////////////////////////////////////
int flgr_list_is_empty(FLGR_List *list) { 
  FLGR_DECLARE_FUNCTION;
  
  if((list->start == NULL) && (list->end == NULL)) { 
    return 1; 
  }else { 
    return 0; 
  } 
} 

//////////////////////////////////////////////////////////////////
/*! Get the number of elements of a list
 *  @param list : FLGR_List
 *  @returns the size of the list
 */
//////////////////////////////////////////////////////////////////
int flgr_list_size(FLGR_List *list) { 
  FLGR_DECLARE_FUNCTION;
  
  return list->nbelt; 
} 
 
//////////////////////////////////////////////////////////////////
/*! Allocate the list
 *  @returns a pointer to FLGR_List
 */
//////////////////////////////////////////////////////////////////
FLGR_List *flgr_list_create() { 
  FLGR_List *list=flgr_malloc(sizeof(FLGR_List));
  FLGR_DECLARE_FUNCTION;
  
  list->start = list->end = NULL; 
  list->nbelt = 0; 
  return list;
}
 
//////////////////////////////////////////////////////////////////
/*! Add an element to the head of the list
 *  @param list : FLGR_List Pointer
 *  @param elt : Pointer to anything
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr_list_add_head(FLGR_List *list,void *elt) { 
  TLink *p; 
 
  FLGR_DECLARE_FUNCTION;
  
  p = (TLink *) flgr_malloc(sizeof(TLink));
  p->elt = elt; 
  p->previous = NULL; 
   
  if(list->nbelt == 0) { 
    p->next = NULL; 
    list->start = list->end = p; 
    list->nbelt = 1; 
  }else { 
    list->start->previous = p; 
    p->next = list->start; 
    list->start = p; 
    list->nbelt++; 
  } 
} 

//////////////////////////////////////////////////////////////////
/*! Add an element to the tail of the list
 *  @param list : FLGR_List Pointer
 *  @param elt : Pointer to anything
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr_list_add_tail(FLGR_List *list,void *elt) { 
  TLink *p; 
 
  FLGR_DECLARE_FUNCTION;
  
  p = (TLink *) flgr_malloc(sizeof(TLink)); 
  p->elt = elt; 
  p->next = NULL; 
 
  if(list->nbelt == 0) { 
    list->start = list->end = p; 
    p->previous = NULL; 
    list->nbelt = 1; 
  }else { 
    p->previous = list->end; 
    list->end->next = p; 
    list->end = p; 
    p->next = NULL; 
    list->nbelt++; 
  } 
} 
 
//////////////////////////////////////////////////////////////////
/*! Delete an element to the Head of the list
 *  @param list : FLGR_List Pointer
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr_list_del_head(FLGR_List *list) { 
  TLink *p; 
 
  FLGR_DECLARE_FUNCTION;
  
  if(list->nbelt != 0) { 
    p = list->start;  
    if(list->nbelt == 1) { 
      list->start = list->end = NULL; 
      list->nbelt = 0; 
    }else { 
      list->start = list->start->next; 
      list->start->previous = NULL; 
      list->nbelt--; 
    } 
    flgr_free(p); 
  } 
} 
 
//////////////////////////////////////////////////////////////////
/*! Delete an element to the Tail of the list
 *  @param list : FLGR_List Pointer
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr_list_del_tail(FLGR_List *list) { 
  TLink *p; 
  
  FLGR_DECLARE_FUNCTION;
  
  if(list->nbelt != 0) { 
    p = list->end; 
    if(list->nbelt == 1) { 
      list->start = list->end = NULL; 
      list->nbelt = 0; 
    }else { 
      list->end = list->end->previous; 
      list->end->next = NULL; 
      list->nbelt--; 
    } 
    flgr_free(p); 
  } 
} 
 
//////////////////////////////////////////////////////////////////
/*! Delete the whole list
 *  @param list : FLGR_List Pointer
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr_list_destroy(FLGR_List *list) {  
  FLGR_DECLARE_FUNCTION;
  
  while(list->nbelt != 0) { 
    flgr_list_del_head(list); 
  } 
  flgr_free(list);
} 
 
//////////////////////////////////////////////////////////////////
/*! Get the Pointer of the List Head Link
 *  @param list : FLGR_List Pointer
 *  @returns void pointer
 */
//////////////////////////////////////////////////////////////////
void *flgr_list_get_head(FLGR_List *list) { 
  FLGR_DECLARE_FUNCTION;
  
  return list->start->elt; 
} 
 
//////////////////////////////////////////////////////////////////
/*! Get the Pointer of the List Tail Link
 *  @param list : FLGR_List Pointer
 *  @returns void pointer
 */
//////////////////////////////////////////////////////////////////
void *flgr_list_get_tail(FLGR_List *list) { 
  FLGR_DECLARE_FUNCTION;
  
  return list->end->elt; 
} 


//////////////////////////////////////////////////////////////////
/*! Push a pointer to anything in the stack (lifo)
 *  @param list : FLGR_List Pointer
 *  @param elt : Pointer to anything
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr_list_stack_push(FLGR_List *list,void *elt) {
  FLGR_DECLARE_FUNCTION;
  
  flgr_list_add_head(list,elt);
}


//////////////////////////////////////////////////////////////////
/*! Pop a pointer to anything in the stack (lifo)
 *  @param list : FLGR_List Pointer
 *  @returns void pointer
 */
//////////////////////////////////////////////////////////////////
void *flgr_list_stack_pop(FLGR_List *list) {
  void *elt=flgr_list_get_head(list);
  FLGR_DECLARE_FUNCTION;
  
  flgr_list_del_head(list);
  return elt;
}
  
  
//////////////////////////////////////////////////////////////////
/*! Put a pointer to anything in the queue (fifo)
 *  @param list : FLGR_List Pointer
 *  @param elt : Pointer to anything
 *  @returns nothing
 */
//////////////////////////////////////////////////////////////////
void flgr_list_queue_add(FLGR_List *list,void *elt) {
  FLGR_DECLARE_FUNCTION;
  
  flgr_list_add_head(list,elt);
}


//////////////////////////////////////////////////////////////////
/*! Get a pointer to anything in the queue (fifo)
 *  @param list : FLGR_List Pointer
 *  @returns void pointer
 */
//////////////////////////////////////////////////////////////////
void *flgr_list_queue_get(FLGR_List *list) {
  void *elt=flgr_list_get_tail(list);
  FLGR_DECLARE_FUNCTION;
  
  flgr_list_del_tail(list);
  return elt;
}


//! @}
